import { ShapeFlags } from "./vnode"

export function render(vnode, container) {
    mount(vnode, container)
}

// 把虚拟dom挂载到container容器里面
function mount(vnode, container) {

    const { shapeFlag } = vnode
    if (shapeFlag & ShapeFlags.ELEMENT) {
        mountElement(vnode, container)
    } else if (shapeFlag & ShapeFlags.TEXT) {
        mountTextNode(vnode, container)
    } else if (shapeFlag & ShapeFlags.FRAGMENT) {
        mountFragment(vnode, container)
    } else {
        mountComponent(vnode, container)
    }
}

function mountElement(vnode, container) {

    // type是元素节点的标签
    const { type, props } = vnode
    const el = document.createElement(type)
    // 把props属性挂到el上
    mountProps(props, el)
    // 把子节点挂载到el上
    mountChildren(vnode, el)
    // 把最终的节点挂载到container中
    container.appendChild(el)
    // 把生成的真实DOM节点放在vnode的el上
    vnode.el = el
}
function mountTextNode(vnode, container) {
    const textNode = document.createTextNode(vnode.children)
    container.appendChild(textNode)
    vnode.el = textNode
}
function mountFragment(vnode, container) {
    mountChildren(vnode, container)
}
function mountComponent(vnode, container) {

}

function mountChildren(vnode, container) {
    const { shapeFlag, children } = vnode
    if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
        mountTextNode(vnode, container)
    } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
        children.forEach(child => {
            mount(child, container)
        })
    }
}
/*
props
{
  class: 'a b',
  style: {
    color: 'red',
    fontSize: '14px',
  },
  onClick: () => console.log('click'),
  checked: '',
  custom: false
}
*/
const domPropsRE = /[A-Z]|^(value|checked|selected|muted|disabled)$/;
function mountProps(props, el) {
    for (const key in props) {
        const value = props[key]
        switch (key) {
            case 'class':
                el.className = value
                break;
            case 'style':
                for (const styleName in value) {
                    el.style[styleName] = value[styleName]
                }
                break;
            default:
                // 处理事件绑定
                if (/^on[a-z]/.test(key)) {
                    // 拿到事件名字
                    const eventName = key.slice(2).toLowerCase()
                    el.addEventListener(eventName, value)
                } else if (domPropsRE.test(key)) {
                    // 如果匹配到正则，则说明可以使用.key的形式给DOM添加属性
                    // 如果是<input type="checkbox" checked> checked不是以键值对的形式存在，会被解析成{checked:''} 所以在这里特殊处理
                    if (value === '' && typeof el[key] === 'boolean') {
                        value = true
                    }
                    el[key] = value
                } else {
                    // 否则只能使用setAttribute自定义添加属性
                    // 使用setAttribute有一点弊端，如果设置的为值为false或者其他非字符串值，则获取的值都是对应的字符串
                    if (value == null || value === false) {
                        el.removeAttribute(key)
                    } else {
                        el.setAttribute(key, value)
                    }
                }
                break;
        }
    }
}